package com.opc.Controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.opc.Common.Code;
import com.opc.Common.MessageConstant;
import com.opc.Common.Result;
import com.opc.Config.CacheUtil;
import com.opc.Mapper.TorqueStandardsMapper;
import com.opc.Mapper.WorkingPositionMapper;
import com.opc.Pojo.*;
import com.opc.Service.WorkingPositionService;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@CrossOrigin
@Slf4j
@RequestMapping("/TorqueStandards")
public class TorqueStandardsController {
    @Autowired
    private TorqueStandardsMapper torqueStandardsMapper;
    @Value("${jwt.path}")
    private String SECRET_KEY;

//    @Qualifier("workingPositionService")
    @Autowired
    private WorkingPositionService workingPositionService;
    @Autowired
    private WorkingPositionMapper workingPositionMapper;

//    @Qualifier("torqueStandardsService")

//    //查询扭力标准
//    @GetMapping("/getTorqueStandards")
//    @CrossOrigin
//    public Result getTorqueStandards1(){
//        LambdaQueryWrapper <TorqueStandards> queryTorqueStandardsWrapper = new LambdaQueryWrapper<>();
//        Object carType = CacheUtil.getFromCache("carType1");
//        List<TorqueStandards> torqueStandards = null;
//        if(carType != null){
//            queryTorqueStandardsWrapper.eq(TorqueStandards::getCarType, carType);
//            torqueStandards = torqueStandardsMapper.selectList(queryTorqueStandardsWrapper);
//        }
//
//        if(torqueStandards == null){
//            return new Result(Code.SELECT_ERR, "无数据");
//        }
//        return new Result(Code.SELECT_OK, torqueStandards);
//    }

    private static String convertLocalDateTimeToString(Date Time) {
        LocalDateTime localDateTime = Time.toInstant()
                .atZone(ZoneId.systemDefault())
                .toLocalDateTime();
        String formattedTime = String.format("%04d:%02d:%02d:%02d:%02d",
                localDateTime.getYear(),
                localDateTime.getMonthValue(),
                localDateTime.getDayOfMonth(),
                localDateTime.getHour(),
                localDateTime.getMinute());
//        log.info("formattedTime是"+formattedTime);
        // 使用 replace() 方法替换第一个 ':' 为 '-'
        // 使用正则表达式替换前两个 ':' 为 '-'
        // 拆分字符串
        String[] parts = formattedTime.split(":");
        // 重新组装字符串
        String newFormattedTime = String.join("-", parts[0], parts[1]) + "-" + parts[2] + " " + parts[3] + ":" + parts[4];
//        log.info("timeFormatter是"+newFormattedTime);
        return newFormattedTime;
    }

    //查询扭力标准
    @GetMapping("/getTorqueStandards")
    @CrossOrigin
    public Result getTorqueStandards(){
        log.info("getTorqueStandards的线程id:{}", Thread.currentThread().getId()+"名"+Thread.currentThread().getName());

        LambdaQueryWrapper <TorqueStandards> queryTorqueStandardsWrapper = new LambdaQueryWrapper<>();
//        queryTorqueStandardsWrapper.groupBy(TorqueStandards::getCarType);

        queryTorqueStandardsWrapper.orderByAsc(TorqueStandards::getWorkingPositionId);
        queryTorqueStandardsWrapper.orderByDesc(TorqueStandards::getUpdateTime);

        List<TorqueStandards> torqueStandards = torqueStandardsMapper.selectList(queryTorqueStandardsWrapper);

        // 按 carType 分组
        Map<String, List<TorqueStandards>> groupedByCarType = torqueStandards.stream()
                .collect(Collectors.groupingBy(TorqueStandards::getCarType));

//        List<TorqueStandardsExt> torqueStandardsExts = new ArrayList<>();
//        List<TorqueStandardsList> torqueStandardsList = new ArrayList<>();

        // 转换为所需的 JSON 结构
        List<Map<String, Object>> result = new ArrayList<>();
        for (Map.Entry<String, List<TorqueStandards>> entry : groupedByCarType.entrySet()) {
            Map<String, Object> group = new HashMap<>();
            group.put("carType", entry.getKey());
            List<Map<String, String>> data = new ArrayList<>();
            for (TorqueStandards torqueStandards0 : entry.getValue()) {
                Map<String, String> torqueData = new HashMap<>();
                WorkingPosition workingPosition = workingPositionMapper.selectById(torqueStandards0.getWorkingPositionId());
                torqueData.put("carType", torqueStandards0.getCarType());
                torqueData.put("workingPositionName", workingPosition.getWorkingPositionName());
                torqueData.put("workingPositionId", String.valueOf(workingPosition.getWorkingPositionId()));
                torqueData.put("Id", String.valueOf(torqueStandards0.getId()));

                torqueData.put("maximumTorque", String.valueOf(torqueStandards0.getMaximumTorque()));
                torqueData.put("minimumTorque", String.valueOf(torqueStandards0.getMinimumTorque()));
                torqueData.put("unit", torqueStandards0.getUnit());
                torqueData.put("updateTimeString", convertLocalDateTimeToString(torqueStandards0.getUpdateTime()));
                data.add(torqueData);
            }
            group.put("data", data);
            result.add(group);
        }

//        for (TorqueStandards torqueStandard : torqueStandards) {
//            TorqueStandardsExt torqueStandardsExt = new TorqueStandardsExt();
//            TorqueStandardsList torqueStandardsList0 = new TorqueStandardsList();
//
//            WorkingPosition workingPosition = workingPositionService.getById(torqueStandard.getWorkingPositionId());
//            torqueStandardsExt.setCarTypeName(torqueStandard.getCarType());
//
//            torqueStandardsList0.setWorkingPositionName(workingPosition.getWorkingPositionName());
//            torqueStandardsList0.setUpdateTimeString(convertLocalDateTimeToString(torqueStandard.getUpdateTime()));
//
//            if(torqueStandardsExt.getCarTypeName().equals(torqueStandard.getCarType())) {
//                BeanUtils.copyProperties(torqueStandard, torqueStandardsList0);
//                torqueStandardsList.add(torqueStandardsList0);
//            }
//
//            torqueStandardsExt.setTorqueStandardsList(torqueStandardsList);
////            torqueStandardsExt.setWorkingPositionName(workingPosition.getWorkingPositionName());
////            torqueStandardsExt.setUpdateTimeString(convertLocalDateTimeToString(torqueStandard.getUpdateTime()));
//            torqueStandardsExts.add(torqueStandardsExt);
//        }

        // 按车型分组
//        Map<String, List<TorqueStandardsExt>> groupedByCarType = torqueStandardsExts.stream()
//                .collect(Collectors.groupingBy(TorqueStandardsExt::getCarType));


        if(result.isEmpty()){//groupedByCarType.isEmpty()
            return new Result(Code.SELECT_ERR, "无数据");
        }

        return new Result(Code.SELECT_OK, result);//groupedByCarType
    }

    private boolean isValidToken(String token) {
//        log.info("SECRET_KEY是"+SECRET_KEY);
//        log.info("token是"+token);
        if (token == null || !token.startsWith("Bearer ")) {
            return false; // 检查令牌格式
        }
        // 提取实际的JWT部分
        token = token.substring(7); // 去掉“Bearer ”前缀
//        log.info("token1是"+token);
        try {
            log.info("解析令牌");
            // 解析令牌
            Claims claims = Jwts.parser()
                    .setSigningKey(SECRET_KEY)
                    .setAllowedClockSkewSeconds(300) // 允许5分钟的时钟偏差
                    .parseClaimsJws(token)
                    .getBody();

            // 获取过期时间
            Date expiration = claims.getExpiration();
            log.info("过期时间："+expiration);
            // 检查是否过期
            return expiration != null && expiration.after(new Date());
        } catch (ExpiredJwtException e) {
            // 处理过期令牌的异常
            log.info("令牌已过期: " + e.getMessage());
            return false;
        } catch (SignatureException e) {
            // 处理签名验证失败的异常
            log.info("令牌签名无效: " + e.getMessage());
            return false;
        } catch (Exception e) {
            // 处理其他可能的异常
            log.info("令牌验证失败: " + e.getMessage());
            return false;
        }
    }

    //修改扭力标准
    @PostMapping("/updateTorqueStandards")
    @Transactional
    @CrossOrigin//
    public Result updateTorqueStandards(@RequestHeader("Authorization") String Token,
                                        @RequestBody TorqueStandardsUpdateCondition torqueStandardsUpdateCondition){
        log.info("updateTorqueStandards的线程id:{}", Thread.currentThread().getId()+"名"+Thread.currentThread().getName());

        // 验证令牌
        if (!isValidToken(Token)) {
            return new Result(Code.LOGIN_ERR, "无效或过期的令牌");
        }
        //不能是负数
//        if(torqueStandardsUpdateCondition.getMinimumTorque() < 0 ||
//                torqueStandardsUpdateCondition.getMaximumTorque() < 0){
//            return new Result(Code.UPDATE_ERR, "最小扭力值和最大扭力值不能小于0");
//        }
        Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
        Set<ConstraintViolation<TorqueStandardsUpdateCondition>> violations =
                validator.validate(torqueStandardsUpdateCondition);

        if (!violations.isEmpty()) {
            StringBuilder errorMessage = new StringBuilder();
            for (ConstraintViolation<TorqueStandardsUpdateCondition> violation : violations) {
                errorMessage.append(violation.getMessage()).append("; ");
            }
            return new Result(Code.UPDATE_ERR, errorMessage.toString());
        }

        Double min = Double.valueOf(torqueStandardsUpdateCondition.getMinimumTorque());
        Double max = Double.valueOf(torqueStandardsUpdateCondition.getMaximumTorque());

        if(min >= max){
            return new Result(Code.UPDATE_ERR, "最小扭力值必须小于最大扭力值");
        }

        TorqueStandards torqueStandards = torqueStandardsMapper.selectById(torqueStandardsUpdateCondition.getId());
        if(torqueStandards == null){
            return new Result(Code.UPDATE_ERR, "该扭力标准数据不存在");
        }

//        if(!torqueStandardsUpdateCondition.getCarType().equals(torqueStandards.getCarType())){
//            LambdaQueryWrapper<TorqueStandards> queryTorqueStandardsWrapper = new LambdaQueryWrapper<>();
//            queryTorqueStandardsWrapper.eq(TorqueStandards::getCarType, torqueStandardsUpdateCondition.getCarType());
//            queryTorqueStandardsWrapper.eq(TorqueStandards::getWorkingPositionId, torqueStandards.getWorkingPositionId());
//            int count = torqueStandardsMapper.selectCount(queryTorqueStandardsWrapper);
//            if(count > 0){
//                return new Result(Code.UPDATE_ERR, "该车型该工位的扭力标准已存在");
//            }
//            torqueStandards.setCarType(torqueStandardsUpdateCondition.getCarType());
//        }

        torqueStandards.setMinimumTorque(min);
        torqueStandards.setMaximumTorque(max);
        torqueStandards.setUpdateTime(new Date());

        int i = torqueStandardsMapper.updateById(torqueStandards);
        if (i>0){
            return new Result(Code.UPDATE_OK, "扭力标准修改成功");
        }else {
            return new Result(Code.UPDATE_ERR, "扭力标准修改失败");
        }
    }

    //修改扭力标准
    @PostMapping("/updateTorqueStandards2")
    @Transactional
    @CrossOrigin//
    public Result updateTorqueStandards2(@RequestHeader("Authorization") String Token,
                                        @RequestBody TorqueStandardsUpdateCondition2 torqueStandardsUpdateCondition2){
        log.info("updateTorqueStandards2的线程id:{}", Thread.currentThread().getId()+"名"+Thread.currentThread().getName());

        // 验证令牌。
        if (!isValidToken(Token)) {
            return new Result(Code.LOGIN_ERR, "无效或过期的令牌");
        }
        //不能是负数
//        if(torqueStandardsUpdateCondition.getMinimumTorque() < 0 ||
//                torqueStandardsUpdateCondition.getMaximumTorque() < 0){
//            return new Result(Code.UPDATE_ERR, "最小扭力值和最大扭力值不能小于0");
//        }
        Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
        Set<ConstraintViolation<TorqueStandardsUpdateCondition2>> violations = validator.validate(torqueStandardsUpdateCondition2);

        if (!violations.isEmpty()) {
            StringBuilder errorMessage = new StringBuilder();
            for (ConstraintViolation<TorqueStandardsUpdateCondition2> violation : violations) {
                errorMessage.append(violation.getMessage()).append("; ");
            }
            return new Result(Code.UPDATE_ERR, errorMessage.toString());
        }

        Double min1 = Double.valueOf(torqueStandardsUpdateCondition2.getMinimumTorque1());
        Double max1 = Double.valueOf(torqueStandardsUpdateCondition2.getMaximumTorque1());

        if(min1 >= max1){
            return new Result(Code.UPDATE_ERR, "车身工位的最小扭力值必须小于最大扭力值");
        }

        Double min2 = Double.valueOf(torqueStandardsUpdateCondition2.getMinimumTorque2());
        Double max2 = Double.valueOf(torqueStandardsUpdateCondition2.getMaximumTorque2());

        if(min2 >= max2){
            return new Result(Code.UPDATE_ERR, "车头工位的最小扭力值必须小于最大扭力值");
        }

           TorqueStandards torqueStandards1 = torqueStandardsMapper.selectById(torqueStandardsUpdateCondition2.getId1());
           if(torqueStandards1 == null){
               return new Result(Code.UPDATE_ERR, "车身工位的扭力标准数据不存在");
           }

        TorqueStandards torqueStandards2 = torqueStandardsMapper.selectById(torqueStandardsUpdateCondition2.getId2());
        if(torqueStandards2 == null){
            return new Result(Code.UPDATE_ERR, "车头工位的扭力标准数据不存在");
        }

           if(!torqueStandardsUpdateCondition2.getCarType().equals(torqueStandards1.getCarType())){
               LambdaQueryWrapper<TorqueStandards> queryTorqueStandardsWrapper = new LambdaQueryWrapper<>();
               queryTorqueStandardsWrapper.eq(TorqueStandards::getCarType, torqueStandardsUpdateCondition2.getCarType());
               queryTorqueStandardsWrapper.eq(TorqueStandards::getWorkingPositionId, torqueStandards1.getWorkingPositionId());
               int count = torqueStandardsMapper.selectCount(queryTorqueStandardsWrapper);
               if(count > 0){
                   return new Result(Code.UPDATE_ERR, "该车型该工位的扭力标准已存在");
               }
               torqueStandards1.setCarType(torqueStandardsUpdateCondition2.getCarType());
           }

        if(!torqueStandardsUpdateCondition2.getCarType().equals(torqueStandards2.getCarType())){
            LambdaQueryWrapper<TorqueStandards> queryTorqueStandardsWrapper = new LambdaQueryWrapper<>();
            queryTorqueStandardsWrapper.eq(TorqueStandards::getCarType, torqueStandardsUpdateCondition2.getCarType());
            queryTorqueStandardsWrapper.eq(TorqueStandards::getWorkingPositionId, torqueStandards2.getWorkingPositionId());
            int count = torqueStandardsMapper.selectCount(queryTorqueStandardsWrapper);
            if(count > 0){
                return new Result(Code.UPDATE_ERR, "该车型该工位的扭力标准已存在");
            }
            torqueStandards2.setCarType(torqueStandardsUpdateCondition2.getCarType());
        }

           torqueStandards1.setMinimumTorque(min1);
           torqueStandards1.setMaximumTorque(max1);
           torqueStandards1.setUpdateTime(new Date());

        torqueStandards2.setMinimumTorque(min2);
        torqueStandards2.setMaximumTorque(max2);
        torqueStandards2.setUpdateTime(new Date());

            int i = torqueStandardsMapper.updateById(torqueStandards1);
            int j = torqueStandardsMapper.updateById(torqueStandards2);

        if (i > 0 && j > 0){
            return new Result(Code.UPDATE_OK, "扭力标准修改成功");
        }else {
            return new Result(Code.UPDATE_ERR, "扭力标准修改失败");
        }
    }

    //添加扭力标准
    @PostMapping("/addTorqueStandards")
    @Transactional
    @CrossOrigin//
    public Result addTorqueStandards(@RequestHeader("Authorization") String Token,
                                     @RequestBody TorqueStandardsAddCondition torqueStandardsAddCondition){
        log.info("addTorqueStandards的线程id:{}", Thread.currentThread().getId()+"名"+Thread.currentThread().getName());

        //System.out.println("添加扭力值"+torqueStandardsAddCondition);
        // 验证令牌
        if (!isValidToken(Token)) {
            return new Result(Code.LOGIN_ERR, "无效或过期的令牌");
        }
        //不能是负数
//        if(torqueStandardsUpdateCondition.getMinimumTorque() < 0 ||
//                torqueStandardsUpdateCondition.getMaximumTorque() < 0){
//            return new Result(Code.UPDATE_ERR, "最小扭力值和最大扭力值不能小于0");
//        }
        Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
        Set<ConstraintViolation<TorqueStandardsAddCondition>> violations = validator.validate(torqueStandardsAddCondition);

        if (!violations.isEmpty()) {
            StringBuilder errorMessage = new StringBuilder();
            for (ConstraintViolation<TorqueStandardsAddCondition> violation : violations) {
                errorMessage.append(violation.getMessage()).append("; ");
            }
            return new Result(Code.SAVE_ERR, errorMessage.toString());
        }

        Double min1 = Double.valueOf(torqueStandardsAddCondition.getMinimumTorque1());
        Double max1 = Double.valueOf(torqueStandardsAddCondition.getMaximumTorque1());

        if(min1 >= max1){
            return new Result(Code.SAVE_ERR, "车身工位的最小扭力值必须小于最大扭力值");
        }

        Double min2 = Double.valueOf(torqueStandardsAddCondition.getMinimumTorque2());
        Double max2 = Double.valueOf(torqueStandardsAddCondition.getMaximumTorque2());

        if(min2 > max2){
            return new Result(Code.SAVE_ERR, "车头工位的最小扭力值必须小于等于最大扭力值");
        }

        LambdaQueryWrapper<TorqueStandards> torqueStandardsLambdaQueryWrapper = new LambdaQueryWrapper<>();
        torqueStandardsLambdaQueryWrapper.eq(TorqueStandards::getCarType, torqueStandardsAddCondition.getCarType());
//        torqueStandardsLambdaQueryWrapper.eq(TorqueStandards::getWorkingPositionId, torqueStandardsAddCondition.getWorkingPositionId1());
        int count = torqueStandardsMapper.selectCount(torqueStandardsLambdaQueryWrapper);
        if (count > 0){
            return new Result(Code.SAVE_ERR, "该车型的扭力标准已存在");
        }

        TorqueStandards torqueStandards1 = new TorqueStandards();
        torqueStandards1.setCarType(torqueStandardsAddCondition.getCarType());//torqueStandardsAddCondition.getWorkingPositionId1()
        torqueStandards1.setWorkingPositionId(MessageConstant.workingPosition1);
        torqueStandards1.setMinimumTorque(min1);
        torqueStandards1.setMaximumTorque(max1);
        torqueStandards1.setUpdateTime(new Date());
        int i = torqueStandardsMapper.insert(torqueStandards1);

        TorqueStandards torqueStandards2 = new TorqueStandards();
        torqueStandards2.setCarType(torqueStandardsAddCondition.getCarType());//torqueStandardsAddCondition.getWorkingPositionId2()
        torqueStandards2.setWorkingPositionId(MessageConstant.workingPosition2);
        torqueStandards2.setMinimumTorque(min2);
        torqueStandards2.setMaximumTorque(max2);
        torqueStandards2.setUpdateTime(new Date());
        int j = torqueStandardsMapper.insert(torqueStandards2);
        //推给前端（没必要）plc监控那边会不断地从数据库推
        if (i>0 && j>0){
            return new Result(Code.SAVE_OK, "扭力标准添加成功");
        }else {
            return new Result(Code.SAVE_ERR, "添加扭力标准失败");
        }
    }

    //删除扭力标准
    @GetMapping("/deleteTorqueStandards")
    @Transactional
    @CrossOrigin
    public Result deleteTorqueStandards(@RequestHeader("Authorization") String Token,
                                        @RequestParam String carType){
        //System.out.println("carType是"+carType);
        // 验证令牌
        if (!isValidToken(Token)) {
            return new Result(Code.LOGIN_ERR, "无效或过期的令牌");
        }

//        TorqueStandards torqueStandards = torqueStandardsMapper.selectById(id);
        LambdaQueryWrapper<TorqueStandards> torqueStandardsLambdaQueryWrapper = new LambdaQueryWrapper<>();
        torqueStandardsLambdaQueryWrapper.eq(TorqueStandards::getCarType, carType);
        List<TorqueStandards> torqueStandards = torqueStandardsMapper.selectList(torqueStandardsLambdaQueryWrapper);
        if(torqueStandards == null){
            return new Result(Code.DELETE_ERR, "该标准数据不存在");
        }
        Object carType1 = CacheUtil.getFromCache("carType1");
        Object carType2 = CacheUtil.getFromCache("carType2");
        if(carType1 != null){
            String carType1String = carType1.toString();
            if(carType1String.equals(carType)){
                return new Result(Code.DELETE_ERR, "该扭力标准数据正在使用中，无法删除");
            }
        }
        if(carType2 != null){
            String carType2String = carType2.toString();
            if(carType2String.equals(carType)){
                return new Result(Code.DELETE_ERR, "该扭力标准数据正在使用中，无法删除");
            }
        }

        List<Long> torqueStandardIds = torqueStandards.stream().map(TorqueStandards::getId).collect(Collectors.toList());

        int i = torqueStandardsMapper.deleteBatchIds(torqueStandardIds);
        if (i>0){
            return new Result(Code.DELETE_OK,"删除成功");
        }else {
            return new Result(Code.DELETE_ERR, "删除失败");
        }
    }

}
